package com.my.structuraltype.flyweight.font;

import java.awt.Color;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.util.WeakHashMap;
/**
 * 
* 
* 描述,这个享元没什么用,但是学到了WeakHashMap,WeakReference,EnumSet等
* @author Hao.Tong
* @version 1.0
* @see 
* @modify
 */
public final class FontData {
	/**
　　* A weak hash map will drop unused references to FontData.
　　* Values have to be wrapped in WeakReferences,
　　* because value objects in weak hash map are held by strong references. 
　　*/
	private static final WeakHashMap<FontData, WeakReference<FontData>> FLY_WEIGHT_DATA = new WeakHashMap<FontData, WeakReference<FontData>>();
	private final int pointSize;
	private final String fontFace;
	private final Color color;
	private final Set<FontEffect> effects;
	
	private FontData(int pointSize, String fontFace, Color color, EnumSet<FontEffect> effects){
		this.pointSize = pointSize;
		this.fontFace = fontFace;
		this.color = color;
		this.effects = Collections.unmodifiableSet(effects);
	}
	
	public static FontData create(int pointSize, String fontFace, Color color, FontEffect... effects) {
		// 创建一个具有指定元素类型的空枚举 set
		EnumSet<FontEffect> effectsSet = EnumSet.noneOf(FontEffect.class);
		for (FontEffect fontEffect : effects) {
			effectsSet.add(fontEffect);
		}
		// We are unconcerned with object creation cost, we are reducing overall memory consumption
		FontData data = new FontData(pointSize, fontFace, color, effectsSet);
		// Retrieve previously created instance with the given values if it (still) exists
		WeakReference<FontData> ref = FLY_WEIGHT_DATA.get(data);
		FontData result = (ref != null) ? ref.get() : null; // Store new font data instance if no matching instance exists
		if (result == null) {
			FLY_WEIGHT_DATA.put(data, new WeakReference<FontData> (data));
			result = data;
		}
		// return the single immutable copy with the given values
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof FontData) {
			if (obj == this) {
				return true;
			}
			FontData other = (FontData) obj;
			return other.pointSize == pointSize && other.fontFace.equals(fontFace) && other.color.equals(color) && other.effects.equals(effects);
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		return (pointSize * 37 + effects.hashCode() * 13) * fontFace.hashCode();
	}
}